package com.liming.coupon.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liming.common.constant.SystemConstants;
import com.liming.common.exception.BusinessException;
import com.liming.common.pojo.dto.coupon.UserHomeCouponPageQuery;
import com.liming.common.pojo.entity.BaseEntity;
import com.liming.common.pojo.entity.coupon.UserCoupon;
import com.liming.common.util.ThreadLocalUtils;
import com.liming.common.util.mybatisplus.MPUtil;
import com.liming.coupon.enums.CouponUseStatusEnum;
import com.liming.coupon.enums.UserCouponStatusEnum;
import com.liming.coupon.mapper.UserCouponMircoMapper;
import com.liming.coupon.service.UserCouponMircoService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liming
 * @date 2025/1/19
 */
@Service
@AllArgsConstructor
public class UserCouponMircoServiceImpl extends ServiceImpl<UserCouponMircoMapper, UserCoupon>
        implements UserCouponMircoService, MPUtil<UserCoupon> {

    @Override
    public Map<Long, Long> userCouponGetFrequency() {
        return lambdaQuery()
                .eq(UserCoupon::getUserId, ThreadLocalUtils.get(SystemConstants.ID))
                .list()
                .stream()
                .collect(Collectors.groupingBy(UserCoupon::getCouponId, Collectors.counting()));
    }

    @Override
    public Map<Long, Long> userCouponUseFrequency() {
        return lambdaQuery()
                .eq(UserCoupon::getUserId, ThreadLocalUtils.get(SystemConstants.ID))
                .eq(UserCoupon::getIsUsed, 1)
                .list()
                .stream()
                .collect(Collectors.groupingBy(UserCoupon::getCouponId, Collectors.counting()));
    }

    @Override
    public long countByUserIdAndCouponId(Long id) {
        return lambdaQuery().eq(UserCoupon::getUserId, ThreadLocalUtils.get(SystemConstants.ID)).eq(UserCoupon::getCouponId, id).count();
    }

    @Override
    public List<Long> userHaveCouponIds() {
        return lambdaQuery()
                .eq(UserCoupon::getUserId, ThreadLocalUtils.get(SystemConstants.ID))
                .eq(UserCoupon::getIsUsed, 0)
                .list()
                .stream()
                .map(UserCoupon::getCouponId)
                .collect(Collectors.toList());
    }

    @Override
    public IPage<Long> userHaveCouponIdsPage(UserHomeCouponPageQuery pageQuery) {
        return lambdaQuery()
                .eq(UserCoupon::getUserId, ThreadLocalUtils.get(SystemConstants.ID))
                .and(ObjectUtil.equal(pageQuery.getStatus(), UserCouponStatusEnum.USABLE.getCode()), query -> query.eq(UserCoupon::getIsUsed, CouponUseStatusEnum.UNUSED.getCode()))
                .and(ObjectUtil.equal(pageQuery.getStatus(), UserCouponStatusEnum.USED.getCode()), query -> query.eq(UserCoupon::getIsUsed, CouponUseStatusEnum.USED.getCode()))
                .and(ObjectUtil.equal(pageQuery.getStatus(), UserCouponStatusEnum.EXPIRED.getCode()), query -> query.le(UserCoupon::getEndDate, LocalDateTime.now()))
                .page(setPage(pageQuery))
                .convert(UserCoupon::getCouponId);
    }

    @Override
    public boolean userUseCoupon(Long couponId) {
        // 查询优惠券
        String userId = ThreadLocalUtils.get(SystemConstants.ID);
        List<UserCoupon> userCoupons = lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getCouponId, couponId)
                .eq(UserCoupon::getIsUsed, CouponUseStatusEnum.UNUSED.getCode())
                .orderByAsc(BaseEntity::getId)
                .list();
        UserCoupon userCoupon = userCoupons.get(0);
        userCoupon.setIsUsed(CouponUseStatusEnum.USED.getCode());
        Assert.isTrue(updateById(userCoupon), () -> new BusinessException("优惠券使用失败"));
        return true;
    }
}
